package com.deschen.security.core.social.qq.connect;

import org.apache.commons.lang3.StringUtils;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.social.oauth2.AccessGrant;
import org.springframework.social.oauth2.OAuth2Template;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import java.nio.charset.Charset;
import java.util.Map;

/**
 * @Author deschen
 * @Create 2019/9/4
 * @Description 继承OAuth2Template，获取Assert_Token令牌
 * @Since 1.0.0
 */
// 文档：https://wiki.connect.qq.com/%E4%BD%BF%E7%94%A8authorization_code%E8%8E%B7%E5%8F%96access_token
public class QQOAuth2Template extends OAuth2Template {

    /**
     * OAuth2Template两个方法介绍
     * 通过Authorization Code获取Access Token--》exchangeForAccess(..)
     * 权限自动续期，获取Access Token--》refreshAccess(String refreshToken, MultiValueMap<String, String> additionalParameters)
     * postForAccessGrant(..)获取令牌，被上面两个方法调用，默认返回Map类型，而实际QQ返回String类型，要重写
     */


    public QQOAuth2Template(String clientId, String clientSecret, String authorizeUrl, String accessTokenUrl) {
        super(clientId, clientSecret, authorizeUrl, accessTokenUrl);
        setUseParametersForClientAuthentication(true);
    }


    /**
     * 添加处理html格式转换器
     * @return
     */
    @Override
    protected RestTemplate createRestTemplate() {
        RestTemplate restTemplate = super.createRestTemplate();
        restTemplate.getMessageConverters().add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
        return restTemplate;
    }

    /**
     * 通过Authorization Code获取Access Token
     * 文档：https://wiki.connect.qq.com/%E4%BD%BF%E7%94%A8authorization_code%E8%8E%B7%E5%8F%96access_token
     * 如果成功返回，即可在返回包中获取到Access Token。 如
     * access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14
     * 而源码返回map类型,需要换成String
     * @param accessTokenUrl
     * @param parameters
     * @return
     */
    @Override
    protected AccessGrant postForAccessGrant(String accessTokenUrl, MultiValueMap<String, String> parameters) {
        //  access_token=FE04************************CCE2&expires_in=7776000&refresh_token=88E4************************BE14
        String responseStr = getRestTemplate().postForObject(accessTokenUrl, parameters, String.class);
        // 切开获取参数值
        String[] params = StringUtils.splitByWholeSeparatorPreserveAllTokens(responseStr, "&");
        String accessToken = StringUtils.substringAfterLast(params[0], "=");
        Long expiresIn = Long.valueOf(StringUtils.substringAfterLast(params[1], "="));
        String refreshToken = StringUtils.substringAfterLast(params[2], "=");
        return new AccessGrant(accessToken, null, refreshToken, expiresIn);
    }


}
